#ifndef _FALCON_PREPROCESSOR_ITERATOR_HPP
#define _FALCON_PREPROCESSOR_ITERATOR_HPP

#define __FALCON_MEMBER_ITERATOR_ARGS(type, name, args)\
	type name() const { return type args; }\

#define __FALCON_MEMBER_ITERATOR_C99(type, name, it)\
	type name() { return (it); }\
	const_##type name() const { return (it); }

#define __FALCON_MEMBER_ITERATOR_ARGS_C99(type, name, args)\
	type name() { return type args; }\
	__FALCON_MEMBER_ITERATOR_ARGS(const_##type, name, args)

#define FALCON_MEMBER_BEGIN_ITERATOR_C99(it)\
	__FALCON_MEMBER_ITERATOR_C99(iterator, begin, it)

#define FALCON_MEMBER_BEGIN_ITERATOR_ARGS_C99(args)\
	__FALCON_MEMBER_ITERATOR_ARGS_C99(iterator, begin, args)

#define FALCON_MEMBER_END_ITERATOR_C99(it)\
	__FALCON_MEMBER_ITERATOR_C99(iterator, end, it)

#define FALCON_MEMBER_END_ITERATOR_ARGS_C99(args)\
	__FALCON_MEMBER_ITERATOR_ARGS_C99(iterator, end, args)

#define FALCON_MEMBER_RBEGIN_ITERATOR_C99(it)\
	__FALCON_MEMBER_ITERATOR_C99(reverse_iterator, rbegin, it)

#define FALCON_MEMBER_RBEGIN_ITERATOR_ARGS_C99(args)\
	__FALCON_MEMBER_ITERATOR_ARGS_C99(reverse_iterator, rbegin, args)

#define FALCON_MEMBER_REND_ITERATOR_C99(it)\
	__FALCON_MEMBER_ITERATOR_C99(reverse_iterator, rend, it)

#define FALCON_MEMBER_REND_ITERATOR_ARGS_C99(args)\
	__FALCON_MEMBER_ITERATOR_ARGS_C99(reverse_iterator, rend, args)

#define FALCON_MEMBER_STD_REVERSE_ITERATOR_C99()\
	FALCON_MEMBER_RBEGIN_ITERATOR_ARGS_C99((end()))\
	FALCON_MEMBER_REND_ITERATOR_ARGS_C99((begin()))


#define FALCON_MEMBER_BEGIN_ITERATOR_C0X(it)\
	FALCON_MEMBER_BEGIN_ITERATOR_C99(it)\
	const_iterator cbegin() const { return (it); }

#define FALCON_MEMBER_BEGIN_ITERATOR_ARGS_C0X(args)\
	FALCON_MEMBER_BEGIN_ITERATOR_ARGS_C99(args)\
	__FALCON_MEMBER_ITERATOR_ARGS(const_iterator, cbegin, args)

#define FALCON_MEMBER_END_ITERATOR_C0X(it)\
	FALCON_MEMBER_END_ITERATOR_C99(it)\
	const_iterator cend() const { return (it); }

#define FALCON_MEMBER_END_ITERATOR_ARGS_C0X(args)\
	FALCON_MEMBER_END_ITERATOR_ARGS_C99(args)\
	__FALCON_MEMBER_ITERATOR_ARGS(const_iterator, cend, args)

#define FALCON_MEMBER_RBEGIN_ITERATOR_C0X(it)\
	FALCON_MEMBER_RBEGIN_ITERATOR_C99(it)\
	const_reverse_iterator crbegin() const { return (it); }

#define FALCON_MEMBER_RBEGIN_ITERATOR_ARGS_C0X(args)\
	FALCON_MEMBER_RBEGIN_ITERATOR_ARGS_C99(args)\
	__FALCON_MEMBER_ITERATOR_ARGS(const_reverse_iterator, crbegin, args)

#define FALCON_MEMBER_REND_ITERATOR_C0X(it)\
	FALCON_MEMBER_REND_ITERATOR_C99(it)\
	const_reverse_iterator crend() const { return (it); }

#define FALCON_MEMBER_REND_ITERATOR_ARGS_C0X(args)\
	FALCON_MEMBER_REND_ITERATOR_ARGS_C99(args)\
	__FALCON_MEMBER_ITERATOR_ARGS(const_reverse_iterator, crend, args)

#define FALCON_MEMBER_STD_REVERSE_ITERATOR_C0X()\
	FALCON_MEMBER_RBEGIN_ITERATOR_ARGS_C0X((end()))\
	FALCON_MEMBER_REND_ITERATOR_ARGS_C0X((begin()))


#if __cplusplus >= 201103L

# define FALCON_MEMBER_BEGIN_ITERATOR(it)\
	FALCON_MEMBER_BEGIN_ITERATOR_C0X(it)

# define FALCON_MEMBER_END_ITERATOR(it)\
	FALCON_MEMBER_END_ITERATOR_C0X(it)

# define FALCON_MEMBER_RBEGIN_ITERATOR(it)\
	FALCON_MEMBER_RBEGIN_ITERATOR_C0X(it)

# define FALCON_MEMBER_REND_ITERATOR(it)\
	FALCON_MEMBER_REND_ITERATOR_C0X(it)

# define FALCON_MEMBER_STD_REVERSE_ITERATOR()\
	FALCON_MEMBER_STD_REVERSE_ITERATOR_C0X()

# define FALCON_MEMBER_BEGIN_ITERATOR_ARGS(args)\
	FALCON_MEMBER_BEGIN_ITERATOR_ARGS_C0X(args)

# define FALCON_MEMBER_END_ITERATOR_ARGS(args)\
	FALCON_MEMBER_END_ITERATOR_ARGS_C0X(args)

# define FALCON_MEMBER_RBEGIN_ITERATOR_ARGS(args)\
	FALCON_MEMBER_RBEGIN_ITERATOR_ARGS_C0X(args)

# define FALCON_MEMBER_REND_ITERATOR_ARGS(args)\
	FALCON_MEMBER_REND_ITERATOR_ARGS_C0X(args)

#else

# define FALCON_MEMBER_BEGIN_ITERATOR(it)\
	FALCON_MEMBER_BEGIN_ITERATOR_C99(it)

# define FALCON_MEMBER_END_ITERATOR(it)\
	FALCON_MEMBER_END_ITERATOR_C99(it)

# define FALCON_MEMBER_RBEGIN_ITERATOR(it)\
	FALCON_MEMBER_RBEGIN_ITERATOR_C99(it)

# define FALCON_MEMBER_REND_ITERATOR(it)\
	FALCON_MEMBER_REND_ITERATOR_C99(it)

# define FALCON_MEMBER_STD_REVERSE_ITERATOR()\
	FALCON_MEMBER_STD_REVERSE_ITERATOR_C99()

# define FALCON_MEMBER_BEGIN_ITERATOR_ARGS(args)\
	FALCON_MEMBER_BEGIN_ITERATOR_ARGS_C99(args)

# define FALCON_MEMBER_END_ITERATOR_ARGS(args)\
	FALCON_MEMBER_END_ITERATOR_ARGS_C99(args)

# define FALCON_MEMBER_RBEGIN_ITERATOR_ARGS(args)\
	FALCON_MEMBER_RBEGIN_ITERATOR_ARGS_C99(args)

# define FALCON_MEMBER_REND_ITERATOR_ARGS(args)\
	FALCON_MEMBER_REND_ITERATOR_ARGS_C99(args)

#endif


#define FALCON_MEMBER_ITERATOR(it_begin, it_end)\
	FALCON_MEMBER_BEGIN_ITERATOR(it_begin)\
	FALCON_MEMBER_END_ITERATOR(it_end)

#define FALCON_MEMBER_ITERATOR_ARGS(args_begin, args_end)\
	FALCON_MEMBER_BEGIN_ITERATOR_ARGS(args_begin)\
	FALCON_MEMBER_END_ITERATOR_ARGS(args_end)

#define FALCON_MEMBER_REVERSE_ITERATOR(it_begin, it_end)\
	FALCON_MEMBER_RBEGIN_ITERATOR(it_begin)\
	FALCON_MEMBER_REND_ITERATOR(it_end)

#define FALCON_MEMBER_REVERSE_ITERATOR_ARGS(args_begin, args_end)\
	FALCON_MEMBER_RBEGIN_ITERATOR_ARGS(args_begin)\
	FALCON_MEMBER_REND_ITERATOR_ARGS(args_end)

#define FALCON_MEMBER_ALL_ITERATOR(it_begin, it_end)\
	FALCON_MEMBER_ITERATOR(it_begin, it_end)\
	FALCON_MEMBER_STD_REVERSE_ITERATOR()

#define FALCON_MEMBER_ALL_ITERATOR_ARGS(args_begin, args_end)\
	FALCON_MEMBER_ITERATOR_ARGS(args_begin, args_end)\
	FALCON_MEMBER_STD_REVERSE_ITERATOR()

#define FALCON_MEMBER_DELEGATE_ITERATOR(container)\
	FALCON_MEMBER_BEGIN_ITERATOR((container).begin())\
	FALCON_MEMBER_END_ITERATOR((container).end())

#define FALCON_MEMBER_DELEGATE_REVERSE_ITERATOR(container)\
	FALCON_MEMBER_RBEGIN_ITERATOR((container).begin())\
	FALCON_MEMBER_REND_ITERATOR((container).end())

#define FALCON_MEMBER_DELEGATE_ALL_ITERATOR(container)\
	FALCON_MEMBER_DELEGATE_ITERATOR(container)\
	FALCON_MEMBER_DELEGATE_REVERSE_ITERATOR(container)

#endif